/*差分约束
* (1)求不等式组的可行解
    源点需要满足的条件: 从源点出发，一定可以走到所有的边，
* 步骤:
    [1]先将每个不等式 xi<= xj+ ck,转化成一条从xj走到xi,长度为ck的一条边
    [2]找一个超级源点，使得该源点一定可以遍历到所有边
    [3]从源点求一遍单源最短路

    结果1: 如果存在负环，!则原不等式组一定无解
    结果2: 如果没有负环，则dist[i]就是原不等式组的一个可行解
* (2)如何求最大值或者最小值，这里的最值指的是每个变量的最值

* 结论: 如果求的是最小值，则应该求最长路;如果求的是最大值，则应该求最短路，

* 问题: 如何转化xi<=c，其中c是一个常数，这类的不等式
* 方法: 建立一个超级源点，0，然后建立0->i，长度是c的边即可，
        以求xi的最大值为例:求所有从xi出发，构成的不等式链xi <= xj+ c1 <= xk + c2 + c1 <= . <= c1+c2+..所计算出的上界，
        最终xi的最大值等于所有上界的最小值。

* LuoGu 数据难度增大 需要Tarjan缩点
*/

#pragma GCC optimize("O1,O2,O3,Ofast")
#pragma GCC optimize("no-stack-protector,unroll-loops,fast-math,inline")
#pragma GCC target("avx,avx2,fma")
#pragma GCC target("sse,sse2,sse3,sse4,sse4.1,sse4.2,ssse3")

#include<iostream>
#include<cstring>
#include<stack>
// #define ONLINE_GUDGE
using namespace std;
#define int long long
const int N = 100010, M = 300010, INF = 0x3f3f3f3f;

int n, m;
int e[M], ne[M], h[N], w[M], idx;
bool st[N]; // 是否从当前点找到最短路径
int dist[N], cnt[N], fa[N];

void AddEdge(int a, int b, int c)
{
    e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx ++ ;
}

int find(int x){    //并查集找根节点
    return fa[x] = (fa[x] == x ? x : find(fa[x]));
}

// spfa 从边出发 适合稀疏图

bool spfa()
{
    memset(st, 0, sizeof st);
    memset(dist, -0x3f, sizeof dist);

    dist[0] = 0;
    stack<int> q; // 栈更快
    q.push(0);
    st[0] = true; // 放入队列 

    while(q.size())
    {
        auto u = q.top();q.pop();

        st[u] = false;

        for(int i = h[u]; ~i; i = ne[i])
        {
            int v = e[i];
            if(dist[v] < dist[u] + w[i]){ // 这个权值更新终点，对整体结果有影响
                dist[v] = dist[u] + w[i];
                cnt[v] = cnt[u] + 1;
                if(cnt[v] >= n+1) return true; // 图中极有可能存在负环, 则原不等式无解
                if(!st[v])
                {
                    st[v] = true; // 放入队列
                    q.push(v);
                }
            }
        }
    }
    return false;

}

signed main()
{
    #ifdef ONLINE_JUDGE

    #else
    freopen("./in.txt","r",stdin);
    #endif
    ios::sync_with_stdio(false);   
	cin.tie(0);

    memset(h, -1, sizeof h);
    cin >> n >> m;
    while(m--)
    {
        int x, a, b; cin >> x >> a >> b;
        if(x == 1) // a==b a>=b b>=a
            AddEdge(a, b, 0), AddEdge(b, a, 0);
        else if(x == 2) // a<b -> a<=b+1
            AddEdge(a, b, 1);
        else if(x == 3) // a>=b+0
            AddEdge(b, a, 0);
        else if(x == 4) // a>b -> a>=b+1
            AddEdge(b, a, 1);
        else // b>=a+0
            AddEdge(a, b, 0);
        
    }

    //超级源点 必须能走到所有边 xi>=x0+0 x0=0
    for(int i=1;i<=n;i++) AddEdge(0,i,1);

    if(spfa()) printf("-1");
    else{
        int res = 0;
        for(int i=1;i<=n;i++) res+=dist[i];
        cout << res << endl;
    }
    return 0;
}